let s = "cbacdcbc"
var removeDuplicateLetters = function (s) {
    // 1. 声明栈，用于存储字典序
    const stack = [];

    // 2. 声明一个 hash 数组，用于记录 stack 中存储的字符
    const visited = new Array(26).fill(false);
    console.log("visited", visited);
    // 3. 声明一个 hash 数组，用于记录字符最后出现的位置
    const lastInx = new Array(26).fill(0);
    console.log("lastInx", lastInx);
    const asset = 'a'.charCodeAt(0); // 偏移量
    console.log("asset", asset);
    for (let i = 0; i < s.length; i++) {
        lastInx[s[i].charCodeAt(0) - asset] = i;

    }
    console.log("lastInx2", lastInx);
    // 4. 从左到右扫描字符串，寻找不重复的最小字典序
    for (let i = 0; i < s.length; i++) {
        // 4-1. 若当前字符已经在栈中，⽆需处理
        if (visited[s[i].charCodeAt(0) - asset]) continue;
        // cbacdcbc
        // 4-2. 若当前字符不在栈中：入栈前需要比较栈内元素是不是 最小字典序
        //    - 栈不为空 && 栈顶元素 > 当前字符 && 栈顶字符在后续字符串还会出现
        //    - 则说明之后会出现更小的字典序，需要出栈栈顶元素
        //    - 直到栈为空或栈顶字符比当前字符小，或栈顶字符在当前位置之后不会再出现
        while (stack.length && stack[stack.length - 1] > s[i] ) {
            visited[stack.pop().charCodeAt(0) - asset] = false; // 更新栈中存在的元素
        }

        // 4-3. 入栈当前字符，并更新 栈中存在的元素
        stack.push(s[i]);
        visited[s[i].charCodeAt(0) - asset] = true;
        console.log(`第${i}次stack,visited`, stack,visited);

    }
    return stack.join('');
};
console.log(removeDuplicateLetters(s));